package affected

import (
	"context"
	"time"

	"github.com/Khan/genqlient/graphql"
	"github.com/google/uuid"
	"github.com/rs/zerolog/log"
	"go.uber.org/fx"

	"github.com/lunasec-io/lunasec/lunatrace/bsl/ingest-worker/pkg/metadata"
	"github.com/lunasec-io/lunasec/lunatrace/gogen/gql"
	"github.com/lunasec-io/lunasec/lunatrace/gogen/gql/types"
)

type Ingester interface {
	Ingest(ctx context.Context, vulnerabilityId string) error
}

type ingesterParams struct {
	fx.In

	GQLClient  graphql.Client
	Ingester   metadata.PackageIngester
	Replicator metadata.APIReplicator
}

type ingester struct {
	ingesterParams
}

func (i ingester) Ingest(ctx context.Context, vulnerabilityId string) error {
	vulnUUID, err := uuid.Parse(vulnerabilityId)
	if err != nil {
		log.Error().
			Err(err).
			Msg("unable to parse vulnerability id")
		return err
	}

	resp, err := gql.GetVulnerabilityMetadata(ctx, i.GQLClient, vulnUUID)
	if err != nil {
		log.Error().
			Err(err).
			Msg("unable to get vulnerability metadata")
		return err
	}
	for _, affected := range resp.Vulnerability_by_pk.Affected {
		if affected.Package.Package_manager == types.NPM {
			time.Sleep(1 * time.Second)
			_, err = i.Ingester.Ingest(ctx, affected.Package.Name)
			if err != nil {
				log.Error().
					Err(err).
					Str("vulnerability", vulnerabilityId).
					Msg("unable to ingest npm package for vulnerability")
				return err
			}
			err = i.Replicator.ReplicatePackages([]string{affected.Package.Name}, true)
			if err != nil {
				log.Error().
					Err(err).
					Msg("unable to replicate npm package download counts")
			}
			err = i.Replicator.ReplicateVersionDownloadCounts(affected.Package.Name, true)
			if err != nil {
				log.Error().
					Err(err).
					Msg("unable to replicate npm package version download counts")
			}
		}
	}
	return nil
}

func NewIngester(params ingesterParams) Ingester {
	return &ingester{
		ingesterParams: params,
	}
}
